broadway: Roundtrip each update to rate limit redraw
authorAlexander Larsson <alexl@redhat.com>
Thu, 23 Nov 2017 09:22:23 +0000 (10:22 +0100)
committerAlexander Larsson <alexl@redhat.com>
Thu, 23 Nov 2017 09:48:29 +0000 (10:48 +0100)
12 files changed:
gdk/broadway/broadway-output.c
gdk/broadway/broadway-output.h
gdk/broadway/broadway-protocol.h
gdk/broadway/broadway-server.c
gdk/broadway/broadway-server.h
gdk/broadway/broadway.js
gdk/broadway/broadwayd.c
gdk/broadway/gdkbroadway-server.c
gdk/broadway/gdkbroadway-server.h
gdk/broadway/gdkeventsource.c
gdk/broadway/gdkprivate-broadway.h
gdk/broadway/gdkwindow-broadway.c

index 193d68e3b3b281c3c87481907b89cbe04367c4a9..036f71b0fa4d4826793e5fa0db8ea8a1b86dcbbe 100644 (file)
@@ -237,6 +237,16 @@ broadway_output_destroy_surface(BroadwayOutput *output,  int id)
   append_uint16 (output, id);
 }
 
+void
+broadway_output_roundtrip (BroadwayOutput *output,
+                           int             id,
+                           guint32         tag)
+{
+  write_header (output, BROADWAY_OP_ROUNDTRIP);
+  append_uint16 (output, id);
+  append_uint32 (output, tag);
+}
+
 void
 broadway_output_set_show_keyboard (BroadwayOutput *output,
                                    gboolean show)
index 024df8e1ca755ed8b51113e288910b1108965cc6..bf35be2aec3f4db24c0c4e62ca4c74333e129219 100644 (file)
@@ -42,6 +42,9 @@ void            broadway_output_lower_surface   (BroadwayOutput *output,
                                                  int             id);
 void            broadway_output_destroy_surface (BroadwayOutput *output,
                                                 int             id);
+void            broadway_output_roundtrip       (BroadwayOutput *output,
+                                                 int             id,
+                                                 guint32         tag);
 void            broadway_output_move_resize_surface (BroadwayOutput *output,
                                                     int             id,
                                                     gboolean        has_pos,
index 7e8a37c59ef5b67362a8580233a615034551a260..41861ef3f181fbfc383a8c9f46a3cc6d1eac6008 100644 (file)
@@ -37,7 +37,8 @@ typedef enum {
   BROADWAY_EVENT_CONFIGURE_NOTIFY = 'w',
   BROADWAY_EVENT_DELETE_NOTIFY = 'W',
   BROADWAY_EVENT_SCREEN_SIZE_CHANGED = 'd',
-  BROADWAY_EVENT_FOCUS = 'f'
+  BROADWAY_EVENT_FOCUS = 'f',
+  BROADWAY_EVENT_ROUNDTRIP_NOTIFY = 'F',
 } BroadwayEventType;
 
 typedef enum {
@@ -60,6 +61,7 @@ typedef enum {
   BROADWAY_OP_UPLOAD_TEXTURE = 't',
   BROADWAY_OP_RELEASE_TEXTURE = 'T',
   BROADWAY_OP_SET_NODES = 'n',
+  BROADWAY_OP_ROUNDTRIP = 'F',
 } BroadwayOpType;
 
 typedef struct {
@@ -128,6 +130,13 @@ typedef struct {
   gint32 height;
 } BroadwayInputConfigureNotify;
 
+typedef struct {
+  BroadwayInputBaseMsg base;
+  gint32 id;
+  guint32 tag;
+  guint32 local;
+} BroadwayInputRoundtripNotify;
+
 typedef struct {
   BroadwayInputBaseMsg base;
   guint32 width;
@@ -155,6 +164,7 @@ typedef union {
   BroadwayInputKeyMsg key;
   BroadwayInputGrabReply grab_reply;
   BroadwayInputConfigureNotify configure_notify;
+  BroadwayInputRoundtripNotify roundtrip_notify;
   BroadwayInputDeleteNotify delete_notify;
   BroadwayInputScreenResizeNotify screen_resize_notify;
   BroadwayInputFocusMsg focus;
@@ -177,6 +187,7 @@ typedef enum {
   BROADWAY_REQUEST_UPLOAD_TEXTURE,
   BROADWAY_REQUEST_RELEASE_TEXTURE,
   BROADWAY_REQUEST_SET_NODES,
+  BROADWAY_REQUEST_ROUNDTRIP,
 } BroadwayRequestType;
 
 typedef struct {
@@ -190,6 +201,12 @@ typedef struct {
   guint32 id;
 } BroadwayRequestDestroyWindow, BroadwayRequestShowWindow, BroadwayRequestHideWindow, BroadwayRequestFocusWindow;
 
+typedef struct {
+  BroadwayRequestBase base;
+  guint32 id;
+  guint32 tag;
+} BroadwayRequestRoundtrip;
+
 typedef struct {
   BroadwayRequestBase base;
   guint32 id;
@@ -257,6 +274,7 @@ typedef union {
   BroadwayRequestNewWindow new_window;
   BroadwayRequestFlush flush;
   BroadwayRequestSync sync;
+  BroadwayRequestRoundtrip roundtrip;
   BroadwayRequestQueryMouse query_mouse;
   BroadwayRequestDestroyWindow destroy_window;
   BroadwayRequestShowWindow show_window;
index 859fa68c41374f71678750d0686ab85cc4f418c2..3f9dfebc16fd6aefe749b6283ebe2726e74f0985 100644 (file)
 #include <string.h>
 #endif
 
+
+typedef struct {
+  int id;
+  guint32 tag;
+} BroadwayOutstandingRoundtrip;
+
 typedef struct BroadwayInput BroadwayInput;
 typedef struct BroadwayWindow BroadwayWindow;
 struct _BroadwayServer {
@@ -81,6 +87,8 @@ struct _BroadwayServer {
   int future_root_y;
   guint32 future_state;
   int future_mouse_in_toplevel;
+
+  GList *outstanding_roundtrips;
 };
 
 struct _BroadwayServerClass
@@ -122,6 +130,7 @@ struct BroadwayWindow {
 };
 
 static void broadway_server_resync_windows (BroadwayServer *server);
+static void send_outstanding_roundtrips (BroadwayServer *server);
 
 static GType broadway_server_get_type (void);
 
@@ -288,6 +297,8 @@ update_event_state (BroadwayServer *server,
        window->y = message->configure_notify.y;
       }
     break;
+  case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
+    break;
   case BROADWAY_EVENT_DELETE_NOTIFY:
     break;
   case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
@@ -429,6 +440,12 @@ update_future_pointer_info (BroadwayServer *server, BroadwayInputPointerMsg *dat
   server->future_mouse_in_toplevel = data->mouse_window_id;
 }
 
+static void
+queue_input_message (BroadwayServer *server, BroadwayInputMsg *msg)
+{
+  server->input_messages = g_list_append (server->input_messages, g_memdup (msg, sizeof (BroadwayInputMsg)));
+}
+
 static void
 parse_input_message (BroadwayInput *input, const unsigned char *message)
 {
@@ -436,6 +453,7 @@ parse_input_message (BroadwayInput *input, const unsigned char *message)
   BroadwayInputMsg msg;
   guint32 *p;
   gint64 time_;
+  GList *l;
 
   memset (&msg, 0, sizeof (msg));
 
@@ -512,6 +530,26 @@ parse_input_message (BroadwayInput *input, const unsigned char *message)
     msg.configure_notify.height = ntohl (*p++);
     break;
 
+  case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
+    msg.roundtrip_notify.id = ntohl (*p++);
+    msg.roundtrip_notify.tag = ntohl (*p++);
+    msg.roundtrip_notify.local = FALSE;
+
+    /* Remove matched outstanding roundtrips */
+    for (l = server->outstanding_roundtrips; l != NULL; l = l->next)
+      {
+        BroadwayOutstandingRoundtrip *rt = l->data;
+
+        if (rt->id == msg.roundtrip_notify.id &&
+            rt->tag == msg.roundtrip_notify.tag)
+          {
+            server->outstanding_roundtrips = g_list_delete_link (server->outstanding_roundtrips, l);
+            g_free (rt);
+            break;
+          }
+      }
+    break;
+
   case BROADWAY_EVENT_DELETE_NOTIFY:
     msg.delete_notify.id = ntohl (*p++);
     break;
@@ -526,8 +564,7 @@ parse_input_message (BroadwayInput *input, const unsigned char *message)
     break;
   }
 
-  server->input_messages = g_list_append (server->input_messages, g_memdup (&msg, sizeof (msg)));
-
+  queue_input_message (server, &msg);
 }
 
 static inline void
@@ -697,7 +734,11 @@ broadway_server_read_all_input_nonblocking (BroadwayInput *input)
        }
 
       if (input->server->input == input)
-       input->server->input = NULL;
+        {
+          send_outstanding_roundtrips (input->server);
+
+          input->server->input = NULL;
+        }
       broadway_input_free (input);
       if (res < 0)
        {
@@ -758,6 +799,23 @@ broadway_server_get_screen_size (BroadwayServer   *server,
   *height = server->root->height;
 }
 
+static void
+broadway_server_fake_roundtrip_reply (BroadwayServer *server,
+                                      gint            id,
+                                      guint32         tag)
+{
+  BroadwayInputMsg msg;
+
+  msg.base.type = BROADWAY_EVENT_ROUNDTRIP_NOTIFY;
+  msg.base.serial = 0;
+  msg.base.time = server->last_seen_time;
+  msg.roundtrip_notify.id = id;
+  msg.roundtrip_notify.tag = tag;
+  msg.roundtrip_notify.local = 1;
+
+  queue_input_message (server, &msg);
+  queue_process_input_at_idle (server);
+}
 
 void
 broadway_server_flush (BroadwayServer *server)
@@ -768,9 +826,28 @@ broadway_server_flush (BroadwayServer *server)
       server->saved_serial = broadway_output_get_next_serial (server->output);
       broadway_output_free (server->output);
       server->output = NULL;
+      send_outstanding_roundtrips (server);
     }
 }
 
+void
+broadway_server_roundtrip (BroadwayServer *server,
+                           gint            id,
+                           guint32         tag)
+{
+  if (server->output)
+    {
+      BroadwayOutstandingRoundtrip *rt = g_new0 (BroadwayOutstandingRoundtrip, 1);
+      rt->id = id;
+      rt->tag = tag;
+      server->outstanding_roundtrips = g_list_prepend (server->outstanding_roundtrips, rt);
+
+      broadway_output_roundtrip (server->output, id, tag);
+    }
+  else
+    broadway_server_fake_roundtrip_reply (server, id, tag);
+}
+
 #if 0
 /* TODO: This is not used atm, is it needed? */
 /* Note: This may be called while handling a message (i.e. sorta recursively) */
@@ -1000,6 +1077,21 @@ start_input (HttpRequest *request)
   g_strfreev (lines);
 }
 
+static void
+send_outstanding_roundtrips (BroadwayServer *server)
+{
+  GList *l;
+
+  for (l = server->outstanding_roundtrips; l != NULL; l = l->next)
+    {
+      BroadwayOutstandingRoundtrip *rt = l->data;
+      broadway_server_fake_roundtrip_reply (server, rt->id, rt->tag);
+    }
+
+  g_list_free_full (server->outstanding_roundtrips, g_free);
+  server->outstanding_roundtrips = NULL;
+}
+
 static void
 start (BroadwayInput *input)
 {
@@ -1011,12 +1103,14 @@ start (BroadwayInput *input)
 
   if (server->output)
     {
+      send_outstanding_roundtrips (server);
       broadway_output_disconnected (server->output);
       broadway_output_flush (server->output);
     }
 
   if (server->input != NULL)
     {
+      send_outstanding_roundtrips (server);
       broadway_input_free (server->input);
       server->input = NULL;
     }
index 4bc81a70d2671304ca961e5bdea6f5be9860751b..d12026118194f8ba40c15e121b62aee66dd61ada 100644 (file)
@@ -29,6 +29,9 @@ BroadwayServer     *broadway_server_on_unix_socket_new       (char             *
 gboolean            broadway_server_has_client               (BroadwayServer   *server);
 void                broadway_server_flush                    (BroadwayServer   *server);
 void                broadway_server_sync                     (BroadwayServer   *server);
+void                broadway_server_roundtrip                (BroadwayServer   *server,
+                                                              gint              id,
+                                                              guint32           tag);
 void                broadway_server_get_screen_size          (BroadwayServer   *server,
                                                              guint32          *width,
                                                              guint32          *height);
index 9f9ca2357f9b6974e02f1b619c699ce37b88f63e..acbd80d236c8b7a59f22f0ab9a98999bfe41bcaf 100644 (file)
@@ -245,6 +245,11 @@ function cmdDeleteSurface(id)
     delete surfaces[id];
 }
 
+function cmdRoundtrip(id, tag)
+{
+    sendInput("F", [id, tag]);
+}
+
 function cmdMoveResizeSurface(id, has_pos, x, y, has_size, w, h)
 {
     var surface = surfaces[id];
@@ -737,6 +742,12 @@ function handleCommands(cmd)
             cmdDeleteSurface(id);
             break;
 
+        case 'F': // RoundTrip
+            id = cmd.get_16();
+            var tag = cmd.get_32();
+            cmdRoundtrip(id, tag);
+            break;
+
         case 'm': // Move a surface
             id = cmd.get_16();
             var ops = cmd.get_flags();
index 50d71f521d76f07ffc76d2fc7d35ee6a11bbf7c3..638b7f9b16c7889ad768fb0b02143933f70e25e5 100644 (file)
@@ -325,6 +325,11 @@ client_handle_request (BroadwayClient *client,
       send_reply (client, request, (BroadwayReply *)&reply_sync, sizeof (reply_sync),
                   BROADWAY_REPLY_SYNC);
       break;
+    case BROADWAY_REQUEST_ROUNDTRIP:
+      broadway_server_roundtrip (server,
+                                 request->roundtrip.id,
+                                 request->roundtrip.tag);
+      break;
     case BROADWAY_REQUEST_QUERY_MOUSE:
       broadway_server_query_mouse (server,
                                    &reply_query_mouse.toplevel,
@@ -728,6 +733,8 @@ get_event_size (int type)
       return sizeof (BroadwayInputGrabReply);
     case BROADWAY_EVENT_CONFIGURE_NOTIFY:
       return  sizeof (BroadwayInputConfigureNotify);
+    case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
+      return  sizeof (BroadwayInputRoundtripNotify);
     case BROADWAY_EVENT_DELETE_NOTIFY:
       return sizeof (BroadwayInputDeleteNotify);
     case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
index 28959a764ead058d46b89a234eb01e5dfbd74e89..fa24e08cd5ffb1571c2f1a012f7b7b1f6364cad9 100644 (file)
@@ -48,7 +48,6 @@ struct _GdkBroadwayServer {
 
   guint process_input_idle;
   GList *incomming;
-  
 };
 
 struct _GdkBroadwayServerClass
@@ -422,7 +421,7 @@ _gdk_broadway_server_sync (GdkBroadwayServer *server)
   BroadwayReply *reply;
 
   serial = gdk_broadway_server_send_message (server, msg,
-                                            BROADWAY_REQUEST_SYNC);
+                                             BROADWAY_REQUEST_SYNC);
   reply = gdk_broadway_server_wait_for_reply (server, serial);
 
   g_assert (reply->base.type == BROADWAY_REPLY_SYNC);
@@ -432,6 +431,19 @@ _gdk_broadway_server_sync (GdkBroadwayServer *server)
   return;
 }
 
+void
+_gdk_broadway_server_roundtrip (GdkBroadwayServer *server,
+                                gint32            id,
+                                guint32           tag)
+{
+  BroadwayRequestRoundtrip msg;
+
+  msg.id = id;
+  msg.tag = tag;
+  gdk_broadway_server_send_message (server, msg,
+                                    BROADWAY_REQUEST_ROUNDTRIP);
+}
+
 void
 _gdk_broadway_server_query_mouse (GdkBroadwayServer *server,
                                  guint32            *toplevel,
index 8ff26ebcfba1bb47b7e558a2da41768d81cad240..aec56699596dadbb79d61ea0d3fde9d9d2b0371d 100644 (file)
@@ -18,6 +18,9 @@ GdkBroadwayServer *_gdk_broadway_server_new                      (const char
                                                                  GError            **error);
 void               _gdk_broadway_server_flush                    (GdkBroadwayServer  *server);
 void               _gdk_broadway_server_sync                     (GdkBroadwayServer  *server);
+void               _gdk_broadway_server_roundtrip                (GdkBroadwayServer *server,
+                                                                  gint32            id,
+                                                                  guint32           tag);
 gulong             _gdk_broadway_server_get_next_serial          (GdkBroadwayServer  *server);
 guint32            _gdk_broadway_server_get_last_seen_time       (GdkBroadwayServer  *server);
 gboolean           _gdk_broadway_server_lookahead_event          (GdkBroadwayServer  *server,
index 0935cc92612a51b10ebd54ed865e78a3214404ba..2f51212ca8f2b977540c0bf0aaa0e4f5d610ade9 100644 (file)
@@ -21,6 +21,7 @@
 #include "gdkdevicemanager-broadway.h"
 
 #include "gdkinternals.h"
+#include "gdkframeclockprivate.h"
 
 #include <stdlib.h>
 
@@ -336,6 +337,12 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
       }
     break;
 
+  case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
+    window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->roundtrip_notify.id));
+    if (window)
+      _gdk_broadway_roundtrip_notify (window, message->roundtrip_notify.tag, message->roundtrip_notify.local);
+    break;
+
   case BROADWAY_EVENT_DELETE_NOTIFY:
     window = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->delete_notify.id));
     if (window)
index 146ff378e2fe5b7a0bbc65806790ad2ba7156e1a..3d8faaa2411728fbe556b439a4bd6aeb47719798 100644 (file)
@@ -79,8 +79,9 @@ gboolean _gdk_broadway_moveresize_handle_event   (GdkDisplay *display,
                                                  BroadwayInputMsg *msg);
 gboolean _gdk_broadway_moveresize_configure_done (GdkDisplay *display,
                                                  GdkWindow  *window);
-
-
+void _gdk_broadway_roundtrip_notify (GdkWindow  *window,
+                                     guint32 tag,
+                                     gboolean local_reply);
 void     _gdk_broadway_selection_window_destroyed (GdkWindow *window);
 void     _gdk_broadway_window_grab_check_destroy (GdkWindow *window);
 void     _gdk_broadway_window_grab_check_unmap (GdkWindow *window,
index 4b71b45c913d321a18a0eb0203c9eb8f6d2f0c49..9eb817398a6b38c1930db2cc0a582a2616ddfd1c 100644 (file)
@@ -37,6 +37,7 @@
 #include "gdkdeviceprivate.h"
 #include "gdkeventsource.h"
 #include <gdk/gdktextureprivate.h>
+#include <gdk/gdkframeclockprivate.h>
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -96,17 +97,6 @@ find_broadway_display (void)
   return display;
 }
 
-static void
-update_dirty_windows_and_sync (void)
-{
-  GdkBroadwayDisplay *display;
-
-  display = GDK_BROADWAY_DISPLAY (find_broadway_display ());
-  g_assert (display != NULL);
-
-  gdk_display_flush (GDK_DISPLAY (display));
-}
-
 static guint flush_id = 0;
 
 static gboolean
@@ -165,11 +155,43 @@ gdk_window_impl_broadway_finalize (GObject *object)
   G_OBJECT_CLASS (gdk_window_impl_broadway_parent_class)->finalize (object);
 }
 
+static gboolean
+thaw_clock_cb (GdkFrameClock *clock)
+{
+  _gdk_frame_clock_thaw (clock);
+  g_object_unref (clock);
+  return G_SOURCE_REMOVE;
+}
+
+void
+_gdk_broadway_roundtrip_notify (GdkWindow  *window,
+                                guint32 tag,
+                                gboolean local_reply)
+{
+  GdkFrameClock *clock = gdk_window_get_frame_clock (window);
+
+  /* If there is no remove web client, rate limit update to once a second */
+  if (local_reply)
+    g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
+  else
+    _gdk_frame_clock_thaw (clock);
+}
+
 static void
 on_frame_clock_after_paint (GdkFrameClock *clock,
                             GdkWindow     *window)
 {
-  update_dirty_windows_and_sync ();
+  GdkDisplay *display = gdk_window_get_display (window);
+  GdkWindowImplBroadway *impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
+  GdkBroadwayDisplay *broadway_display;
+
+  _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
+
+  broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+  _gdk_broadway_server_roundtrip (broadway_display->server, impl->id, _gdk_display_get_next_serial (display));
+
+  gdk_display_flush (display);
 }
 
 static void